package org.ricks.virtual;

import org.ricks.ioc.utils.Logger;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;

public class Player implements AutoCloseable {
    private static final int MAX_QUEUE_SIZE = 1000;
    private static final long SHUTDOWN_TIMEOUT_MS = 5000;
    private static final int QUEUE_SIZE_WARNING_THRESHOLD = 100;
    private static final long SLOW_TASK_THRESHOLD_MS = 10;
    private static final long CRITICAL_SLOW_TASK_THRESHOLD_MS = 1000;
    private static final int MAX_CONSECUTIVE_SLOW_TASKS = 5;

    public final String id;
    private final BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>(MAX_QUEUE_SIZE);
    private final ExecutorService executor;
    private final AtomicLong rejectedTasks = new AtomicLong();
    private final AtomicLong processedTasks = new AtomicLong();
    private final AtomicLong totalProcessingTimeMs = new AtomicLong();
    private final AtomicLong slowTaskCount = new AtomicLong();
    private final AtomicLong criticalSlowTaskCount = new AtomicLong();
    private final AtomicInteger consecutiveSlowTasks = new AtomicInteger();
    private volatile boolean isClosing = false;
    private final ReentrantLock shutdownLock = new ReentrantLock();

    // 玩家状态数据，确保所有修改都通过任务队列进行
    private volatile PlayerState state = new PlayerState();

    // 用于跨玩家数据修改的协调器
    private static final PlayerDataCoordinator dataCoordinator = new PlayerDataCoordinator();

    public Player(String id) {
        this.id = id;
        this.executor = Executors.newSingleThreadExecutor(Thread.ofVirtual().name("Player-" + id).factory());
        startProcessing();
        PlayerManager.registerPlayer(this);
    }

    private void startProcessing() {
        executor.submit(() -> {
            while (!Thread.currentThread().isInterrupted() && !isClosing) {
                try {
                    Runnable task = taskQueue.poll(100, TimeUnit.MILLISECONDS);
                    if (task != null) {
                        task.run();
                        processedTasks.incrementAndGet();
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    Logger.error("Player " + id + " unexpected error in task processing", e);
                    // 防止异常导致循环退出，记录后继续处理
                }
            }
            Logger.debug("Player " + id + " processing loop exited");
        });
    }

    private Runnable wrapTask(Runnable task, String taskType) {
        return () -> {
            long startTime = System.nanoTime();
            try {
                task.run();
            } catch (Exception e) {
                Logger.error("Player " + id + " task " + taskType + " failed", e);
                // 根据任务类型决定是否需要进行恢复操作
                handleTaskFailure(taskType, e);
            } finally {
                long durationMs = (System.nanoTime() - startTime) / 1_000_000;
                totalProcessingTimeMs.addAndGet(durationMs);

                // 慢任务检测和记录
                if (durationMs > SLOW_TASK_THRESHOLD_MS) {
                    slowTaskCount.incrementAndGet();
                    int consecutive = consecutiveSlowTasks.incrementAndGet();

                    if (durationMs > CRITICAL_SLOW_TASK_THRESHOLD_MS) {
                        criticalSlowTaskCount.incrementAndGet();
                        Logger.warn("Player " + id + " CRITICAL SLOW task " + taskType +
                                " executed in " + durationMs + "ms");
                    } else {
                        Logger.debug("Player " + id + " slow task " + taskType +
                                " executed in " + durationMs + "ms");
                    }

                    // 连续慢任务报警
                    if (consecutive >= MAX_CONSECUTIVE_SLOW_TASKS) {
                        Logger.warn("Player " + id + " has " + consecutive +
                                " consecutive slow tasks, possible performance issue");
                    }
                } else {
                    consecutiveSlowTasks.set(0); // 重置连续慢任务计数
                }
            }
        };
    }

    private void handleTaskFailure(String taskType, Exception e) {
        // 根据任务类型实施不同的恢复策略
        if ("save-data".equals(taskType)) {
            // 数据保存失败，尝试重新加入队列
            Logger.warn("Player " + id + " data save failed, will retry");
            // 实际实现中可以考虑重试机制
        }
        // 其他任务类型的失败处理...
    }

    public void submitTask(Runnable task, boolean retryOnFull, String taskType) {
        if (isClosing) {
            rejectedTasks.incrementAndGet();
            Logger.warn("Player " + id + " is closing, task rejected");
            return;
        }

        if (getPendingTasks() > QUEUE_SIZE_WARNING_THRESHOLD) {
            Logger.warn("Player " + id + " queue size " + getPendingTasks() + " exceeds warning threshold");
        }

        Runnable wrappedTask = wrapTask(task, taskType);

        if (!taskQueue.offer(wrappedTask)) {
            if (retryOnFull) {
                try {
                    boolean success = taskQueue.offer(wrappedTask, 500, TimeUnit.MILLISECONDS);
                    if (!success) {
                        rejectedTasks.incrementAndGet();
                        Logger.warn("Player " + id + " queue full after retry, task rejected");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    rejectedTasks.incrementAndGet();
                    Logger.warn("Player " + id + " task submission interrupted", e);
                }
            } else {
                rejectedTasks.incrementAndGet();
                Logger.warn("Player " + id + " queue full, task rejected");
            }
        }
    }

    // 重载方法，兼容旧代码
    public void submitTask(Runnable task, boolean retryOnFull) {
        submitTask(task, retryOnFull, "unknown");
    }

    public void disconnect() {
        shutdownLock.lock();
        try {
            if (isClosing) {
                return;
            }
            isClosing = true;

            // 先尝试优雅关闭
            executor.shutdown();

            try {
                if (!executor.awaitTermination(SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                    Logger.warn("Player " + id + " shutdown timed out, forcing shutdown");
                    List<Runnable> remainingTasks = executor.shutdownNow();
                    if (!remainingTasks.isEmpty()) {
                        Logger.warn("Player " + id + " discarded " + remainingTasks.size() + " pending tasks");
                        // 尝试保存关键任务数据
                        saveCriticalTasksData(remainingTasks);
                    }
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
                Logger.warn("Player " + id + " shutdown interrupted", e);
            }
        } finally {
            PlayerManager.unregisterPlayer(this);
            shutdownLock.unlock();
        }
    }

    private void saveCriticalTasksData(List<Runnable> tasks) {
        // 实现关键任务数据的保存逻辑
        // 例如：解析任务内容，保存玩家状态等
        Logger.info("Player " + id + " attempting to save data from " + tasks.size() + " abandoned tasks");
    }

    // 监控接口
    public int getPendingTasks() {
        return taskQueue.size();
    }

    public long getRejectedTasks() {
        return rejectedTasks.get();
    }

    public long getProcessedTasks() {
        return processedTasks.get();
    }

    public long getAverageProcessingTimeMs() {
        long processed = processedTasks.get();
        if (processed == 0) return 0;
        return totalProcessingTimeMs.get() / processed;
    }

    public long getSlowTaskCount() {
        return slowTaskCount.get();
    }

    public long getCriticalSlowTaskCount() {
        return criticalSlowTaskCount.get();
    }

    public boolean isHealthy() {
        return !isClosing &&
                consecutiveSlowTasks.get() < MAX_CONSECUTIVE_SLOW_TASKS &&
                taskQueue.size() < MAX_QUEUE_SIZE * 0.8;
    }

    @Override
    public void close() {
        disconnect();
    }

    // 玩家状态修改方法 - 所有修改都通过任务队列确保线程安全
    public void updateState(PlayerState newState) {
        submitTask(() -> {
            // 使用数据协调器确保跨玩家数据一致性
            dataCoordinator.coordinateUpdate(this, newState);
            this.state = newState;
        }, true, "update-state");
    }

    // 跨玩家数据修改方法
    public void transferTo(Player otherPlayer, int amount) {
        submitTask(() -> {
            // 通过协调器确保原子性操作
            dataCoordinator.coordinateTransfer(this, otherPlayer, amount);
        }, true, "transfer-resources");
    }

    // 获取玩家状态快照（线程安全）
    public PlayerState getStateSnapshot() {
        // 创建防御性副本
        return new PlayerState(state);
    }

    // 内部状态类
    public static class PlayerState {
        // 玩家状态字段
        private int level;
        private int score;
        // 其他状态字段...

        public PlayerState() {
            // 初始化默认状态
        }

        public PlayerState(PlayerState other) {
            // 复制构造函数
            this.level = other.level;
            this.score = other.score;
        }

        // getters and setters...
    }
}

// 玩家数据协调器，确保跨玩家操作的一致性
class PlayerDataCoordinator {
    private final Map<String, ReentrantLock> playerLocks = new ConcurrentHashMap<>();

    public void coordinateUpdate(Player player, Player.PlayerState newState) {
        // 获取玩家专属锁，确保同一玩家的状态更新是串行的
        ReentrantLock lock = playerLocks.computeIfAbsent(player.id, id -> new ReentrantLock());
        lock.lock();
        try {
            // 执行状态更新
            // 这里可以添加验证逻辑确保状态一致性
        } finally {
            lock.unlock();
        }
    }

    public void coordinateTransfer(Player from, Player to, int amount) {
        // 确保跨玩家操作的原子性
        // 使用固定顺序获取锁避免死锁
        String firstId = from.id.compareTo(to.id) < 0 ? from.id : to.id;
        String secondId = from.id.compareTo(to.id) < 0 ? to.id : from.id;

        ReentrantLock firstLock = playerLocks.computeIfAbsent(firstId, id -> new ReentrantLock());
        ReentrantLock secondLock = playerLocks.computeIfAbsent(secondId, id -> new ReentrantLock());

        firstLock.lock();
        try {
            secondLock.lock();
            try {
                // 执行转账操作，确保两个玩家的状态同时更新
                // 这里可以实现更复杂的一致性检查
            } finally {
                secondLock.unlock();
            }
        } finally {
            firstLock.unlock();
        }
    }
}
